package controller

import (
	"fmt"
	"io/ioutil"
	"scoce_estimate/config"
	"scoce_estimate/data_process"
	"scoce_estimate/db_connect"
	"scoce_estimate/model"
	"scoce_estimate/status"
	"scoce_estimate/utils/decode"
)

func SetUpDataPrepare(fp string, prefix string, level int, solution_buffer chan *model.Solution, total_buffer chan *model.Total_score_info) {

	fileInfoList, err := ioutil.ReadDir(fp)
	if err != nil {
		fmt.Println("读取考生代码出错")
		fmt.Println(err.Error())
		return
	}

	if level == status.CSPJ_LEVEL {
		data_process.SetOverallTotalCSPJ(len(fileInfoList))
	} else if level == status.CSPS_LEVEL {
		data_process.SetOverallTotalCSPS(len(fileInfoList))
	}
	titles, title_map, _ := config.GetTitleAndMap(level)

	for _, f := range fileInfoList {
		user_id := prefix + f.Name()
		db_connect.CreateUser(prefix + f.Name())
		for _, pid := range title_map {
			data_process.Insert(user_id, pid, -1, status.NOT_IN_QUEUE)
		}
		total := data_process.GetTotal(user_id, titles, title_map)
		if total >= 0 {
			data_process.AddRanking(user_id, total, level)
		}
	}
}

func SetUpData(fp string, m map[string]int, prefix string, level int, solution_buffer chan *model.Solution, total_buffer chan *model.Total_score_info) {
	fileInfoList, err := ioutil.ReadDir(fp)
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	titles, title_map, _ := config.GetTitleAndMap(level)

	for i, f := range fileInfoList {
		fmt.Printf("%d/%d\n", i+1, len(fileInfoList))
		user := &model.User{User_id: prefix + f.Name()}

		for title, pid := range m {
			codePath := fmt.Sprintf("%s/%s/%s/%s.cpp", fp, f.Name(), title, title)
			source, err := ioutil.ReadFile(codePath)
			if err != nil {
				fmt.Println("读取文件失败", codePath)
				fmt.Println(err.Error())
			}
			source, err = decode.GbkToUtf8(source)

			if err != nil {
				fmt.Println("解码失败")
				fmt.Println(err.Error())
			} else {
				solution := &model.Solution{User_id: user.User_id, Problem_id: pid}
				solution_buffer <- solution
				fmt.Println("Upload ", user.User_id, pid)
				db_connect.UploadSolution(user, pid, len(source), string(source))
			}
		}
		total := data_process.GetTotal(user.User_id, titles, title_map)
		if total >= 0 {
			data_process.AddRanking(user.User_id, total, level)
		} else {
			total_buffer <- &model.Total_score_info{User_id: user.User_id, Level: level}
		}

	}
}

func Process() {
	cspj_sol_buffer := make(chan *model.Solution)
	csps_sol_buffer := make(chan *model.Solution)
	cspj_total_score_buffer := make(chan *model.Total_score_info)
	csps_total_score_buffer := make(chan *model.Total_score_info)
	go func() {

		SetUpDataPrepare(config.Cspj_file_path, config.Cspj_prefix, status.CSPJ_LEVEL, cspj_sol_buffer, cspj_total_score_buffer)
		SetUpDataPrepare(config.Csps_file_path, config.Csps_prefix, status.CSPS_LEVEL, csps_sol_buffer, csps_total_score_buffer)

		SetUpData(config.Cspj_file_path, config.Cspj_map, config.Cspj_prefix, status.CSPJ_LEVEL, cspj_sol_buffer, cspj_total_score_buffer)
		SetUpData(config.Csps_file_path, config.Csps_map, config.Csps_prefix, status.CSPS_LEVEL, csps_sol_buffer, csps_total_score_buffer)
	}()
	go data_process.Updater(cspj_sol_buffer, status.CSPJ_LEVEL, cspj_total_score_buffer)
	go data_process.Updater(cspj_sol_buffer, status.CSPJ_LEVEL, cspj_total_score_buffer)
	go data_process.Updater(csps_sol_buffer, status.CSPS_LEVEL, csps_total_score_buffer)
	go data_process.Updater(csps_sol_buffer, status.CSPS_LEVEL, csps_total_score_buffer)
	go data_process.Total_score_consume(cspj_total_score_buffer, csps_total_score_buffer)
	go data_process.Total_score_consume(cspj_total_score_buffer, csps_total_score_buffer)
}
